package service

import (
	"ia/apps/admin/web/dts/sin"
	"ia/apps/admin/web/dts/sout"
	"ia/common/model/modeladmin"
	"ia/common/storage"
	"ia/common/support"
	"ia/common/support/define"

	"github.com/kataras/golog"
	"github.com/kataras/iris/v12"
	"gorm.io/gorm"
)

type AdminPolicyService interface {
	Delete(ctx iris.Context)
	Table(ctx iris.Context)
	ReloadPolicy(ctx iris.Context)
	List(ctx iris.Context)
	Log(ctx iris.Context)
}

func NewAdminPolicyService() *adminPolicyService {
	return &adminPolicyService{}
}

type adminPolicyService struct{}

func (impl *adminPolicyService) Delete(ctx iris.Context) {
	var (
		code       define.Code
		err        error
		idList     = make([]int, 0)
		policyList = make([]*modeladmin.AdminPolicy, 0)
	)
	if err = ctx.ReadJSON(&idList); err != nil {
		goto ERR
	}
	if len(idList) > 0 {
		if err = storage.GDB1.Find(&policyList, "id in ?", idList).Error; err != nil {
			goto ERR
		}
	}

	if err = storage.GDB1.Transaction(func(tx *gorm.DB) error {
		if err = tx.Delete(&modeladmin.AdminPolicy{}, "id in ?", idList).Error; err != nil {
			return err
		}
		if err = tx.Delete(&modeladmin.AdminRolePolicy{}, "pid in ?", idList).Error; err != nil {
			return err
		}
		for _, v := range policyList {
			if err = tx.Delete(&modeladmin.CasbinRule{},
				"ptype='p' AND v2=? AND v3=? AND v4=?", v.V2, v.V3, v.V4).Error; err != nil {
				return err
			}
		}
		return nil
	}); err != nil {
		goto ERR
	}
	support.Ok_(ctx)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (impl *adminPolicyService) Table(ctx iris.Context) {
	var (
		code   define.Code
		err    error
		in     sin.VxeTableIn
		total  int64
		result = make([]*modeladmin.AdminPolicy, 0)
	)
	if err = ctx.ReadQuery(&in); err != nil {
		goto ERR
	}
	if err = storage.GDB1.Model(&modeladmin.AdminPolicy{}).Count(&total).Error; err != nil {
		goto ERR
	}
	if err = storage.GDB1.
		Offset(in.Offset()).Limit(in.PageSize).
		Find(&result).Error; err != nil {
		goto ERR
	}
	support.VxeTableData(ctx, in.PageSize, in.CurrentPage, total, result, nil)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (impl *adminPolicyService) ReloadPolicy(ctx iris.Context) {
	var code define.Code

	if err := storage.GDB1.Transaction(func(tx *gorm.DB) error {
		for _, v := range sout.GIfaceList {
			policy := modeladmin.AdminPolicy{
				GroupName: v.GroupName,
				Name:      v.Name,
				Memo:      v.Memo,
				IsSystem:  true,
				V1:        define.GConfig.App.Own.Tenant,
				V2:        v.Path,
				V3:        v.Method,
				V4:        ".*",
				V5:        "",
			}
			if err := tx.Where(&policy).FirstOrCreate(&policy).Error; err != nil {
				return err
			}
		}
		// TODO 1 删除后来又取消的;2 调整后来又修改的
		return nil
	}); err != nil {
		golog.Errorf("错误：%s", err)
		support.InternalServerError(ctx, code)
		return
	}
	support.Ok_(ctx)
}

func (impl *adminPolicyService) List(ctx iris.Context) {
	var (
		code   define.Code
		err    error
		result = make([]*modeladmin.AdminPolicy, 0)
	)
	if err = storage.GDB1.Find(&result).Error; err != nil {
		goto ERR
	}
	support.Ok(ctx, result)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}

func (impl *adminPolicyService) Log(ctx iris.Context) {
	var (
		code define.Code
		err  error
		in   sin.AdminPolicyOfLogIn
	)
	if err = ctx.ReadJSON(&in); err != nil {
		goto ERR
	}
	if len(in.IdList) > 0 {
		if err = storage.GDB1.Model(&modeladmin.AdminPolicy{}).
			Where("id in ?", in.IdList).Update("logable", in.Operation).Error; err != nil {
			goto ERR
		}
		if err := storage.GDB1.Find(&sout.GPolicyLogList, "logable=TRUE").Error; err != nil {
			golog.Error("刷新policy log 缓存失败,错误=%v", err)
		}
	}
	support.OkTip(ctx, nil)
	return
ERR:
	golog.Errorf("错误：%s", err)
	support.InternalServerError(ctx, code)
}
